// This code was adapted from code at the following website:
// http://www.captain.at/howto-simple-serial-port-test-example.php

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>

static const char *devicenm = "/dev/ttyS0";
static int fd;

#define PULSE_WIDTH_IN_MSEC (1)

int writeport(int fd, unsigned char *chars, int len)
{
  int n = write(fd, chars, len);
  if (n < 0)
  {
    fputs("write failed!\n", stderr);
    return 0;
  }
  return 1;
}

#if 0
int readport(int fd, char *result)
{
  int iIn = read(fd, result, 254);
  result[iIn-1] = 0x00;
  if (iIn < 0)
  {
    if (errno == EAGAIN)
    {
      printf("SERIAL EAGAIN ERROR\n");
      return 0;
    }
    else
    {
      printf("SERIAL read error %d %s\n", errno, strerror(errno));
      return 0;
    }
  }
  return 1;
}
#endif

int getbaud(int fd)
{
  struct termios termAttr;
  int inputSpeed = -1;
  speed_t baudRate;
  tcgetattr(fd, &termAttr);
  /* Get the input speed.                              */
  baudRate = cfgetispeed(&termAttr);
  switch (baudRate)
  {
  case B0:
    inputSpeed = 0;
    break;
  case B50:
    inputSpeed = 50;
    break;
  case B110:
    inputSpeed = 110;
    break;
  case B134:
    inputSpeed = 134;
    break;
  case B150:
    inputSpeed = 150;
    break;
  case B200:
    inputSpeed = 200;
    break;
  case B300:
    inputSpeed = 300;
    break;
  case B600:
    inputSpeed = 600;
    break;
  case B1200:
    inputSpeed = 1200;
    break;
  case B1800:
    inputSpeed = 1800;
    break;
  case B2400:
    inputSpeed = 2400;
    break;
  case B4800:
    inputSpeed = 4800;
    break;
  case B9600:
    inputSpeed = 9600;
    break;
  case B19200:
    inputSpeed = 19200;
    break;
  case B38400:
    inputSpeed = 38400;
    break;
  }
  return inputSpeed;
}

int initport(int fd)
{
  struct termios options = {0};
  
  // Get the current options for the port...
  tcgetattr(fd, &options);
  
  // Set the baud rates to 9600...
  cfsetispeed(&options, B9600);
  cfsetospeed(&options, B9600);

  // Enable the receiver and set local mode...
  //options.c_cflag |= (CLOCAL | CREAD);
  options.c_lflag &= ~ICANON;
  options.c_cflag |= CLOCAL;

  options.c_cflag &= ~PARENB;
  options.c_cflag &= ~CSTOPB;
  options.c_cflag &= ~CSIZE;
  options.c_cflag |= CS8;
  
#warning "Try http://ece-www.colorado.edu/~ecen5623/ecen/ex/ecen5623/Solaris_Unix/Unix_Serial_Test/serialutil.c"
  // Set the new options for the port...
  tcsetattr(fd, TCSANOW, &options);
  return 1;
}

int main(int argc, char **argv)
{
  unsigned char sCmd[254];

  fd = open(devicenm, O_RDWR | O_NOCTTY | O_NDELAY);
  if (fd == -1)
  {
    perror("open_port: Unable to open /dev/ttyS0 - ");
    exit(-1);
  }
  else
  {
    fcntl(fd, F_SETFL, 0);
  }
  
  memset(sCmd, 0, sizeof(sCmd));

  printf("baud=%d\n", getbaud(fd));
  initport(fd);
  printf("baud=%d\n", getbaud(fd));

  sCmd[0]=0xFF;
  writeport(fd, &sCmd[0], 1);
  usleep(PULSE_WIDTH_IN_MSEC*1000);
  
  sCmd[1]=atoi(argv[1]);
  writeport(fd, &sCmd[1], 1);
  usleep(PULSE_WIDTH_IN_MSEC*1000);

  sCmd[2]=atoi(argv[2]);
  writeport(fd, &sCmd[2], 1);
  usleep(PULSE_WIDTH_IN_MSEC*1000);

  printf("written:%02x %02x %02x\n", sCmd[0], sCmd[1], sCmd[2]);

  sleep(1);

  close(fd);
  return 0;
}
